﻿using DropNet.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using sync.Client;
using sync.Library;

namespace sync.Server
{
    class SSyncSVtoCL
    {

        public static List<string> listlogSV;
        bool syncDataToCL = true;
        int idx = 0;
        public SSyncSVtoCL()
        {
            sRequestServer srq = new sRequestServer();
            srq.loadServer();
            listlogSV = new List<string>();
        }
        //Delete file/folder in local path(get delta from server) 
        public void SyncDelete(bool syncDataToCL)
        {
            if (idx >= listlogSV.Count)
                idx=0;
            string line = listlogSV[idx];
            string fullPathSV = line.Substring(line.LastIndexOf("|FP|") + 4, line.LastIndexOf("|ID|") - line.LastIndexOf("|FP|") - 4),
                     fullPathCL = sClientInfo.pathClient + fullPathSV.Replace("/", @"\"),
                     fileName = line.Substring(line.LastIndexOf("|FN|") + 4, line.LastIndexOf("|FP|") - line.LastIndexOf("|FN|") - 4),
                     pathSV = fullPathSV.Substring(0, fullPathSV.Length - fileName.Length),
                     meta = "null", stdateModify = "";
            if (line.Contains("|DT|"))
            {
                meta = line.Substring(line.LastIndexOf("|ID|") + 4, line.LastIndexOf("|DT|") - line.LastIndexOf("|ID|") - 4);
                stdateModify = line.Substring(line.LastIndexOf("|DT|") + 4, line.Length - line.LastIndexOf("|DT|") - 4);
                try
                {
                }
                catch (Exception ex)
                {
                    SMessage.Error = ("Datetime parse fail :" + "\n" + ex.Message); idx++;
                }
            }
            if (File.Exists(fullPathCL))//if file exist in client
            {
                syncDataToCL = false;
                try
                {
                    // Delete file from Client
                    File.Delete(fullPathCL);
                    listlogSV = listlogSV.Where(w => w != line).ToList();
                    new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                    syncDataToCL = true;
                }
                catch (Exception ex)
                {
                    SMessage.Error = "Delete \"" + fileName + "\" fail \n" + ex.Message; idx++;
                    syncDataToCL = true;
                }


            }
            if (Directory.Exists(fullPathCL))//if folder exist in client
            {
                if (Directory.GetFiles(fullPathCL).Length == 0)
                {
                    syncDataToCL = false;
                    try
                    {
                        //Delete folder from Client
                        Directory.Delete(fullPathCL);
                        listlogSV = listlogSV.Where(w => w != line).ToList();
                        new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                        syncDataToCL = true;
                    }
                    catch (Exception ex)
                    {
                        SMessage.Error = "Delete \"" + fileName + "\" fail \n" + ex.Message; idx++;
                        syncDataToCL = true;
                    }
                }
            }
            else//if file or folder not exist in client
            {
                listlogSV = listlogSV.Where(w => w != line).ToList();
                new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                syncDataToCL = true;
            }
        }
        //Download file/create folder in local path (get delta from server)
        public void syncCreate(bool syncDataToCL)
        {
            if (idx >= listlogSV.Count)
                idx=0;
            string line = listlogSV[idx];
            string fullPathSV = line.Substring(line.LastIndexOf("|FP|") + 4, line.LastIndexOf("|ID|") - line.LastIndexOf("|FP|") - 4),
                   fullPathCL = sClientInfo.pathClient + fullPathSV.Replace("/", @"\"),
                   fileName = line.Substring(line.LastIndexOf("|FN|") + 4, line.LastIndexOf("|FP|") - line.LastIndexOf("|FN|") - 4),
                   pathSV = fullPathSV.Substring(0, fullPathSV.Length - fileName.Length),
                   meta = "null", stdateModify = "";
            DateTime dateModify = DateTime.Now;
            if (line.Contains("|DT|"))
            {
                meta = line.Substring(line.LastIndexOf("|ID|") + 4, line.LastIndexOf("|DT|") - line.LastIndexOf("|ID|") - 4);
                stdateModify = line.Substring(line.LastIndexOf("|DT|") + 4, line.Length - line.LastIndexOf("|DT|") - 4);
                try
                {
                    dateModify = DateTime.Parse(stdateModify);
                }
                catch (Exception ex)
                {
                    SMessage.Error = ("Datetime parse fail :" + "\n" + ex.Message);
                }
            }
            if (meta == "Is_Dir:False")
                        {
            syncDataToCL = false;
            bool fileExist = false;
            sRequestServer._client.SearchAsync(fileName, pathSV,
          (responseS) =>
          {
              MetaData[] fileSearch = responseS.ToArray();
              for (int i = 0; i < fileSearch.Count(); i++)
              {
                  if (fileSearch[i].Is_Dir) continue;
                  if (fileSearch[i].Path.ToLower() == fullPathSV.ToLower())
                      fileExist = true;
              }
              if (!fileExist)
              {
                  listlogSV = listlogSV.Where(w => w != line).ToList();
                  new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                  syncDataToCL = true;
              }
              else
              {
                  sRequestServer._client.GetFileAsync(fullPathSV,
                   (response) =>
                   {
                       try
                       {
                           if (File.Exists(fullPathCL))
                           {
                               if (File.GetLastWriteTime(fullPathCL) < dateModify)
                               {
                                   //if (File.ReadAllBytes(fullPathCL).Length == response.RawBytes.Length)

                                   File.Delete(fullPathCL);
                                   new sFileMethods().AppendAllBytes(fullPathCL, response.RawBytes);
                               }
                           }
                           else
                               new sFileMethods().AppendAllBytes(fullPathCL, response.RawBytes);
                           listlogSV = listlogSV.Where(delegate(string w) { return w != line; }).ToList();
                           new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                       }
                       catch (Exception ex)
                       {
                           SMessage.Error = string.Format("Getfile |Delete  \"{0}\" fail \n{1}", fileName, ex.Message); idx++;
                       }
                       syncDataToCL = true;
                   },
                       (error) =>
                       {
                           SMessage.Error = "Download \"" + fileName + "\" fail \n" + error.Message; idx++;
                           syncDataToCL = true;
                       });
              }
          },
          error =>
          {
              SMessage.Error = "Server not response \n" + error.Message; idx++;
              syncDataToCL = true;
          });
                        }
            else
            {
                if (Directory.Exists(fullPathCL))
                {
                    listlogSV = listlogSV.Where(w => w != line).ToList();
                    new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                    syncDataToCL = true;
                }
                else
                {
                    syncDataToCL = false;
                    try
                    {
                        Directory.CreateDirectory(fullPathCL);
                        new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                        syncDataToCL = true;
                    }
                    catch (Exception ex)
                    {
                        SMessage.Error = "Create folder \"" + fileName + "\" fail \n" + ex.Message;
                        idx++;
                        syncDataToCL = true;
                    }
                }
            }
        }
        //Add change file on Server to List
        private void addTolistlogSV()
        {
            sClientInfo.cursor = new sRegistryMethods().Registry_Get("Cursor");
            DeltaPage detaPage = sRequestServer._client.GetDelta(sClientInfo.cursor);
            sClientInfo.cursor = detaPage.Cursor;
            if (detaPage.Entries.Count > 0)
            {
                int countD = 0;
                foreach (DeltaEntry de in detaPage.Entries)
                {
                    if (countD == detaPage.Entries.Count - 1)
                    {
                        new sRegistryMethods().Registry_Set("Cursor", sClientInfo.cursor);
                    }
                    string isDir = "|ID|null",
                    dateModify = "",
                    fileName = de.Path.Substring(de.Path.LastIndexOf("/") + 1, de.Path.Length - de.Path.LastIndexOf("/") - 1);
                    if (de.MetaData != null)
                    {
                        isDir = "|ID|Is_Dir:" + de.MetaData.Is_Dir.ToString();
                        dateModify = "|DT|" + de.MetaData.ModifiedDate.ToString();
                    }
                    listlogSV.Add("|FN|" + fileName + "|FP|" + de.Path + isDir + dateModify);
                    countD++;
                }
            }
            if (detaPage.Entries.Count == 0)
                return;
        }
        private void syncToClient()
        {
            if (listlogSV.Count == 0)
                return;
            int countListSV=listlogSV.Count;
            while(listlogSV.Count>0)
            {
                if (idx >= listlogSV.Count - 1)
                    idx = 0;
                string line = listlogSV[idx];
                if (line.Trim() != "" || line != "null")
                {
                    string meta = "null";
                    if (line.Contains("|DT|"))
                    {
                        meta = line.Substring(line.LastIndexOf("|ID|") + 4, line.LastIndexOf("|DT|") - line.LastIndexOf("|ID|") - 4);
                    }
                    if (meta == "null")//delete file or folder from client
                    {
                        SyncDelete(syncDataToCL);
                    }
                    else
                    {
                        syncCreate(syncDataToCL);
                    }
                }
                else
                {
                    listlogSV = listlogSV.Where(w => w != line).ToList();
                    syncDataToCL = true;
                }
                idx++;
            }
        }
        public async void asyncToClient()
        {
            try
            {
                Task t1 = Task.Factory.StartNew(() => addTolistlogSV());
                await t1;
                Task t4 = Task.Factory.StartNew(() => syncToClient());
            }
            catch (Exception ex)
            { SMessage.Error = ("AsyncToClient" + "\n" + ex.Message); }
        }
    }
}
